package com.ddwl.message.service;

import com.ddwl.common.exception.CommonException;
import com.ddwl.common.exception.ExceptionCode;
import com.ddwl.common.feign.api.UserApi;
import com.ddwl.common.util.ObjectUtil;
import com.ddwl.message.model.Sos;
import com.ddwl.message.repository.SosRepository;
import com.ddwl.schema.bo.base.LocationBo;
import com.ddwl.schema.bo.base.PageBo;
import com.ddwl.schema.bo.message.InformerBo;
import com.ddwl.schema.bo.message.SosBo;
import com.ddwl.schema.bo.message.SosPageBo;
import com.ddwl.schema.vo.base.PageVo;
import com.ddwl.schema.vo.message.SosVo;
import com.ddwl.schema.vo.user.UserVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Fu Zhaohui
 * @version 1.0.0
 * @date 2019/8/8 14:50
 */
@Service
@RequiredArgsConstructor
public class SosService {

    private final SosRepository sosRepository;
    private final UserApi userApi;

    public SosVo getById(String id) {
        Sos entity = sosRepository.findById(id).orElse(null);
        SosVo vo = new SosVo();
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }

    public void create(SosBo bo) {
        Sos entity = new Sos();
        BeanUtils.copyProperties(bo, entity);
        entity.setStatus((byte) 0);
        entity.setGmtCreated(Instant.now());
        sosRepository.save(entity);
    }

    public void update(SosBo bo) {
        Optional<Sos> optional = sosRepository.findById(bo.getId());
        if (!optional.isPresent()) {
            throw new CommonException(ExceptionCode.DATA_NOT_EXISTS);
        }
        Sos entity = optional.get();
        BeanUtils.copyProperties(bo, entity, ObjectUtil.getNullFields(bo));
        entity.setGmtModified(Instant.now());
        sosRepository.save(entity);
    }

    public void audit(SosBo bo) {
        Optional<Sos> optional = sosRepository.findById(bo.getId());
        if (!optional.isPresent()) {
            throw new CommonException(ExceptionCode.DATA_NOT_EXISTS);
        }
        Sos entity = optional.get();
        BeanUtils.copyProperties(bo, entity, ObjectUtil.getNullFields(bo));
        entity.setStatus(bo.getStatus());
        sosRepository.save(entity);
        if (bo.getStatus() == 1) {
//            GeoLoc geoLoc = userGrpcClient.lastLocation(entity.getUserId());
//            if (geoLoc != null) {
//                Iterator<UserReply> iterator = userGrpcClient.nearUser(geoLoc);
//                while (iterator.hasNext()) {
//                    PushReq.Builder builder = PushReq.newBuilder();
//                    builder.setAlert("亲，附近有小孩走丢，麻烦留意一下，非常感谢！！");
//                    builder.addUserIds(iterator.next().getId());
//                    builder.putFields("type", "sos");
//                    builder.putFields("data", entity.getId());
//                    if (StringUtils.hasText(entity.getDeviceId())) {
//                        builder.putFields("deviceId", entity.getDeviceId());
//                    }
//                    builder.setProduct(BaseEnum.ProductEnum.MALL.getName());
//                    gateGrpcClient.appPush(builder.build());
//                }
//            }
        }
    }


    public void delete(String id) {
        sosRepository.delete(id);
    }

    public PageVo<SosVo> page(PageBo<SosPageBo> pageBo) {
        PageVo<SosVo> pageVo = new PageVo<>();
        BeanUtils.copyProperties(pageBo, pageVo);
        Page<Sos> page = sosRepository.findPage(pageBo);
        pageVo.setTotal(page.getTotalElements());
        List<Sos> entities = page.getContent();
        if (entities.isEmpty()) {
            pageVo.setData(new ArrayList<>(0));
            return pageVo;
        }
        List<String> userIds = new ArrayList<>();
        entities.forEach(entity -> {
            userIds.add(entity.getUserId());
            List<Sos.Informer> informers = entity.getInformers();
            if (!CollectionUtils.isEmpty(informers)) {
                userIds.addAll(informers.stream().map(Sos.Informer::getUserId).collect(Collectors.toList()));
            }
        });
        entities.stream().map(Sos::getUserId).collect(Collectors.toList());
        List<UserVo> users = userApi.getUserByIds(userIds).getResult();
        Map<String, UserVo> userMap = users.stream().collect(Collectors.toMap(UserVo::getId, Function.identity()));
        pageVo.setData(entities.stream().map(entity -> {
            SosVo vo = new SosVo();
            BeanUtils.copyProperties(entity, vo);
            vo.setUser(userMap.get(entity.getUserId()));
            List<Sos.Informer> informers = entity.getInformers();
            if (!CollectionUtils.isEmpty(informers)) {
                vo.setInfomers(informers.stream().map(informer -> {
                    SosVo.InformerVo informerVo = vo.new InformerVo();
                    BeanUtils.copyProperties(informer, informerVo);
                    informerVo.setUser(userMap.get(informer.getUserId()));
                    return informerVo;
                }).collect(Collectors.toList()));
            }
            return vo;
        }).collect(Collectors.toList()));
        return pageVo;
    }

    /**
     * 提供线索
     *
     * @param bo
     */
    public void informer(InformerBo bo) {
        Optional<Sos> optional = sosRepository.findById(bo.getSosId());
        if (!optional.isPresent()) {
            throw new CommonException(ExceptionCode.DATA_NOT_EXISTS);
        }
        Sos entity = optional.get();
        Sos.Informer informer = entity.new Informer();
        BeanUtils.copyProperties(bo, informer);
        informer.setGmtUpload(Instant.now());
        List<Sos.Informer> informers = entity.getInformers();
        if (informers == null) {
            informers = new ArrayList<>();
            entity.setInformers(informers);
        }
        informers.add(informer);
        sosRepository.save(entity);
    }

    /**
     * 帮互已解决
     */
    public void resolve(InformerBo bo) {
        Optional<Sos> optional = sosRepository.findById(bo.getSosId());
        if (!optional.isPresent()) {
            throw new CommonException(ExceptionCode.DATA_NOT_EXISTS);
        }
        Sos entity = optional.get();
        List<Sos.Informer> informers = entity.getInformers();
        if (!CollectionUtils.isEmpty(informers)) {
            informers.forEach(informer -> {
                if (informer.getUserId().equals(bo.getUserId())) {
                    informer.setValid(true);
                }
            });
        }
        entity.setStatus((byte) 3);
        entity.setGmtModified(Instant.now());
        sosRepository.save(entity);
    }

    public List<SosVo> near(LocationBo loc) {

        List<Sos> entities = sosRepository.findNear(loc);
        return entities.stream().map(entity -> {
            SosVo vo = new SosVo();
            BeanUtils.copyProperties(entity, vo);
            return vo;
        }).collect(Collectors.toList());
    }
}
